package webreg.model.swing;

import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.ListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import webreg.model.Disciplin;
import webreg.model.container.DisciplinContainer;


/** This class wraps multiple 
 * disciplins in one container class for persistence.
 * 
 * @author STKNOLL
 */
public class DisciplinContainerListModel extends DisciplinContainer implements ListModel, ListDataListener {
	private Vector<ListDataListener> mListeners;
	private String mFilter;
	
	/** Constructor of a disciplin container */
	public DisciplinContainerListModel() {
		super();
		mListeners = new Vector<ListDataListener>();
		mFilter = "";
	}
	
	/** Constructor of a disciplin container
	 * 
	 * @param disciplins The disciplins to store.
	 */
	public DisciplinContainerListModel(TreeSet<Disciplin> disciplins) {
		super(disciplins);
		mListeners = new Vector<ListDataListener>();
		mFilter = "";
	}
	
	/** Copy constructor for disciplin container
	 * 
	 * Private copy constructor for a disciplin container
	 * 
	 * @param toCopy The disciplin container to copy
	 */
	public DisciplinContainerListModel (DisciplinContainerListModel toCopy) {
		super(toCopy);
		mListeners = new Vector<ListDataListener>();
		mFilter = "";
	}
	
	/** Implementation of the equals method.
	 * 
	 * @param toCompare The disciplin container to compare with
	 * @return True, if disciplin matches
	 */
	public boolean equals(DisciplinContainerListModel toCompare) {
		return super.equals(toCompare);
	}

	public void addElementAt(int arg0, Disciplin inValue) {
		super.getDisciplins().add(inValue);
		intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, arg0, arg0));
	}		
	
	public void editElementAt(int arg0, Disciplin inValue) {
		int pos = 0;
		for(Iterator<Disciplin> iter = getDisciplins().iterator(); iter.hasNext(); iter.next() ) {
			if (pos == arg0) {
				removeElementAt(pos);
				addElementAt(0, inValue);
				break;
			}
			pos++;
		}
		//super.getDisciplins().toArray()[arg0] = inValue;
		contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, arg0));
	}	
	
	public void removeElementAt(int arg0) {
		Disciplin toDelete = (Disciplin) getDisciplins().toArray()[arg0];
		getDisciplins().remove(toDelete);	
		intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, arg0, arg0));
	}	
		
	public void applyFilter(String inFilter) {
		mFilter = "" + inFilter;
		System.out.println("Apply filter: '" + mFilter + "'");
		contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, getSize() ) );
	}

	
	@Override
	public void addListDataListener(ListDataListener l) {
		mListeners.add(l);		
	}

	@Override
	public Object getElementAt(int index) {
		// return a string here, or the disciplin would be displayed well
		if ( mFilter.equals("") == false)
		{
			int positionWithFilter = 0;
			Pattern p = Pattern.compile("^" + mFilter + "(.)*$");
			Matcher m = null;

			for(Iterator<Disciplin> iter = getDisciplins().iterator(); iter.hasNext(); ) {
				Disciplin toCheck = (Disciplin)iter.next();
				m = p.matcher( toCheck.toString() );
				// make a regexp match
				if ( m.matches() == true ) {
					if (positionWithFilter == index) {
						return toCheck;
					}
					else {
						positionWithFilter ++;
					}
				}
			}
			//TODO throw exception here!!!
			System.out.println("Should never happen! Could not find element at pos: " + index + " with filter applied");
			return null;
		}
		else {		
			return super.getDisciplins().toArray()[index];
		}
	}

	@Override
	public int getSize() {
		if (mFilter.equals("") == false )
		{
			int sizeWithFilter = 0;
			Pattern p = Pattern.compile("^" + mFilter + "(.)*$");
			Matcher m = null;

			for(Iterator<Disciplin> iter = getDisciplins().iterator(); iter.hasNext(); ) {
				Disciplin toCheck = (Disciplin)iter.next();
				m = p.matcher( toCheck.toString() );
				System.out.println("Try to match disciplin: " + toCheck.toString() + " with pattern: " + p.pattern() );
				// make a regexp match
				if ( m.matches() == true ) {
					sizeWithFilter ++;
				}
			}
//			System.out.println("Disciplin list size with filter: " + sizeWithFilter);
			return sizeWithFilter;
		}
		else {
//			System.out.println("Disciplin list size without filter: " + getDisciplins().size() );
			return getDisciplins().size();
		}
	}

	@Override
	public void removeListDataListener(ListDataListener l) {
		mListeners.remove(l);		
	}
	
	@Override
	public void contentsChanged(ListDataEvent e) {
		for(Iterator<ListDataListener> iter = mListeners.iterator(); iter.hasNext(); ) {
			ListDataListener inList = (ListDataListener) iter.next();
			inList.contentsChanged(e);
		}	
	}

	@Override
	public void intervalAdded(ListDataEvent e) {
		for(Iterator<ListDataListener> iter = mListeners.iterator(); iter.hasNext(); ) {
			ListDataListener inList = (ListDataListener) iter.next();
			inList.intervalAdded(e);
		}		
	}

	@Override
	public void intervalRemoved(ListDataEvent e) {
		for(Iterator<ListDataListener> iter = mListeners.iterator(); iter.hasNext(); ) {
			ListDataListener inList = (ListDataListener) iter.next();
			inList.intervalRemoved(e);
		}
	}				
}
